package com.e3.template.tgf;

import java.util.ArrayList;
import java.util.List;

import com.e3.template.model.TGFTreeModel;
import com.e3.web.core.client.GXTHelper;
import com.e3.web.core.client.GwtAsyncCallback;
import com.e3.web.widget.client.BaseAction;
import com.e3.web.widget.client.MyMenu;
import com.e3.web.widget.client.MyMenuItem;
import com.e3.web.widget.model.MyTreeModel;
import com.extjs.gxt.ui.client.data.DataProxy;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.google.gwt.user.client.rpc.AsyncCallback;

public abstract class TGFTreePanelAsync<D extends TGFTreeModel> extends TGFTreePanel<D> {
	
	private GwtAsyncCallback<List<D>> callback;

	@Override
	protected void onTreeDataSelected(D model) {
		if(model == null){
			return;
		}
		MyTreeModel tModel = (MyTreeModel)model;
		D pModel = getTreeStore().getParent(model);
		tModel.setParentModel(pModel);
		List<D> subModels = getTreeStore().getChildren(model);
		
		if(subModels!=null&&subModels.size()>0){
			for (D d : subModels) {
				((MyTreeModel)d).setParentModel(model);
			}
			listenerManager.notifyTreeDataSelected(model, subModels);
			return;
		}
		
		if(tModel.hasChildren()){
			GXTHelper.maskQuery(this);
			excuteLoadModelChildren(model,getTreeAsyncCallBack(model));
			return;
		}
		else{
			List<D> models = new ArrayList<D>(1);
			models.add(model);
			listenerManager.notifyTreeDataSelected(model, models);
		}
	}

	@Override
	protected void onMnuEvent(BaseAction action) {
		if(action == TGFStateMachine.REFRESH_ACTION){
			D model = getTreePanel().getSelectionModel().getSelectedItem();
			if(model == null){
				return;
			}
			getTreeLoader().loadChildren(model);
		}
	}
	
	@Override
	public void beforeSetTreeContextMenu(Menu menu){
		MyMenuItem item = new MyMenuItem(TGFStateMachine.REFRESH_ACTION);
		item.addSelectionListener(mnuSelectListener);
		menu.add(item);
		((MyMenu)menu).setMenuOwner(this);
	}
	
	
	public GwtAsyncCallback<List<D>> getTreeAsyncCallBack(final D pModel){
		if(callback == null){
			callback = new GwtAsyncCallback<List<D>>(this) {
				@Override
				public void doSuccess(List<D> result) {
					successLoadTreeChildren(pModel,result);
				}
			};
		}
		return callback;
	}

	public DataProxy<List<D>> getTreeLoaderProxy(){
		RpcProxy<List<D>> proxy = new RpcProxy<List<D>>() {
			@SuppressWarnings("unchecked")
			protected void load(Object loadConfig,AsyncCallback<List<D>> callback) {
				D model = (D)loadConfig;
				excuteLoadModelChildren(model,callback);
			}
		};
		return proxy;
	}
	
	protected void onTreeLoadSuccess(D loadConfig, List<D> result) {
		if(result!=null&&result.size()==1){
			D model = result.get(0);
			if(isRootModel(model)){
				model.set(getTreeDisplayFieldName(),getRootDisplayName());
			}
		}
	}
	
	protected abstract boolean isRootModel(D model);
	
	public abstract void excuteLoadModelChildren(D pModel,AsyncCallback<List<D>> callback);
	
	public abstract String getRootDisplayName();
	
}
